﻿/*------------------------------------------------
 Author:ShenDuo
 CreatedDate:2019.3.19
 UpdatedDate:
 version:0.1
 ------------------------------------------------*/

using System;
using System.Collections.Generic;
using System.Linq;
using TrainsTraining.Model;

namespace TrainsTraining
{
    /// <summary>
    ///     Matrix graph settings
    /// </summary>
    public static class MGraphHelper
    {
        /// <summary>
        ///     Set graph datas from input routes
        /// </summary>
        public static void SetMGraph()
        {
            //input routes
            string input = Console.ReadLine();
            if (input != null)
            {
                //Set graph datas
                SetMGraph(input.Split(','), PathHelper.Nodes);
#if DEBUG
                //output matrix graph when debug mode
                DebugOutputMGraph(PathHelper.Nodes);
#endif
            }
        }

        /// <summary>
        ///     Output matrix graph
        /// </summary>
        /// <param name="nodes">node list</param>
        public static void DebugOutputMGraph(List<Node> nodes)
        {
            Console.Write("\t");
            //output column title
            IEnumerable<string> columTitles = nodes.SelectMany(x => x.EdgeList.Select(y => y.EndNodeId)).Distinct();
            foreach (string columTitle in columTitles)
                Console.Write(columTitle + "\t");

            //output row data
            nodes.ForEach(x =>
            {
                Console.Write("\n");
                Console.Write(x.Id + "\t");
                foreach (string columTitle in columTitles)
                {
                    //output matched data with column header
                    Edge edge = x.EdgeList.FirstOrDefault(y => y.EndNodeId == columTitle);
                    if (edge != null)
                        Console.Write(edge.Weight + "\t");
                    else
                        Console.Write("\t");
                }
            });
            Console.Write("\n");
        }

        /// <summary>
        ///     Set graph datas
        /// </summary>
        /// <param name="routes">input routes</param>
        /// <param name="nodes">the node list to be filled</param>
        public static void SetMGraph(string[] routes, List<Node> nodes)
        {
            routes.ToList().ForEach(route =>
            {
                //check route
                char[] chars = route.ToCharArray();
                if (chars.Length != 3) return;
                string nodeId = chars.First().ToString();
                if (string.IsNullOrEmpty(nodeId)) return;
                string endNodeId = chars[1].ToString();
                if (string.IsNullOrEmpty(endNodeId)) return;

                //weight  - edge distance
                int weight = Convert.ToInt32(chars.LastOrDefault().ToString());

                //check node exist
                Node node = nodes.FirstOrDefault(y => y.Id == nodeId);
                if (node != null)
                {
                    //check edge exist
                    Edge edge = node.EdgeList.FirstOrDefault(z => z.EndNodeId == endNodeId);

                    if (edge != null)
                        //update weight
                        edge.Weight = weight;
                    else
                        //add new edge
                        node.EdgeList.Add(new Edge { EndNodeId = endNodeId, Weight = weight });
                }
                else
                //add new node and edge
                {
                    nodes.Add(new Node(nodeId) { EdgeList = { new Edge { EndNodeId = endNodeId, Weight = weight } } });
                }
            });
        }
    }
}